import {BaseBinaryNodeModel} from "./BaseBinaryNodeModel.js";

/**
 * @description 二叉树构建类
 * @class {BaseBinaryTreeModel}
 * @author hhx
 * @date 2024-11-13 16:11
 * @version 0.1.2
 */
export class BaseBinaryTreeModel {

    /**
     * @description 根节点值
     * @private
     * @type {BaseBinaryNodeModel} 二叉树节点对象
     */
    _root = null;

    /**
     * @description 二叉树构造函数
     * @public
     * @constructor
     * @param value {number} 根节点值
     */
    constructor(value) {

        //根节点值
        this.root = new BaseBinaryNodeModel(value);

    }

    //========================== 内部属性 ==========================

    /**
     * @description 获取 根节点
     * @property
     * @protected
     * @return {BaseBinaryNodeModel} 树节点
     */
    get root() {
        return this._root;
    }

    /**
     * @description 设置 根节点
     * @property
     * @protected
     * @param value {BaseBinaryNodeModel} 树节点对象
     */
    set root(value) {
        this._root = value;
    }

    //========================== 属性方法 ==========================

    /**
     * @description 获取树节点
     * @public
     * @return {BaseBinaryNodeModel} 树节点
     */
    getRoot() {
        return this.root;
    }

    /**
     * @description 设置树节点
     * @public
     * @param value {BaseBinaryNodeModel} 树节点对象
     */
    setRoot(value) {
        this.root = value;
    }

    /**
     * @description 是否有 根节点
     * @public
     * @return {boolean} true 是 false 否
     */
    hasRoot() {
        return this.root !== null;
    }

    //========================== 接口 ==========================

    /**
     * @description 设置左子树值
     * @public
     * @param value {number} 左子树值
     */
    setLeft(value) {

        //创建树节点
        let node = this.buildNode(value);

        //判断节点是否为空
        if (this.hasRoot()) {

            //递归遍历
            this.dfsLeftNode(this.root, node);
        }

    }

    /**
     * @description 设置右节点
     * @public
     * @param value {number} 节点值
     */
    setRight(value) {

        //创建节点
        let node = this.buildNode(value);

        //判断根节点是否存在
        if (this.hasRoot()) {

            //递归遍历
            this.dfsRightNode(this.root, node);
        }
    }

    /**
     * @description 获取树的深度
     * @public
     * @default 当前树节点
     * @return {number} 树的深度
     */
    getTreeDeep(root = this.root) {

        //递归终止条件 判断节点是否为空
        if (root === null) {
            return 0;
        }

        //左节点深度
        let left = this.getTreeDeep(root.left);

        //右节点深度
        let right = this.getTreeDeep(root.right);

        //最大节点深度
        return Math.max(left, right) + 1;

    }

    //========================== 内部方法 ==========================

    /**
     * @description 构建树节点
     * @private
     * @param value {number} 节点值
     * @return {BaseBinaryNodeModel} 树节点
     */
    buildNode(value) {
        return new BaseBinaryNodeModel(value);
    }

    /**
     * @description 遍历树的左节点
     * @private
     * @param root {BaseBinaryNodeModel} 根节点
     * @param node {BaseBinaryNodeModel} 子节点
     */
    dfsLeftNode(root, node) {

        //判断左子结点是否为空
        if (root.left === null) {
            return root.left = node;
        }

        //递归遍历左子节点
        return this.dfsLeftNode(root.left, node);

    }

    /**
     * @description 深度遍历右节点
     * @private
     * @param root {BaseBinaryNodeModel} 根节点
     * @param node {BaseBinaryNodeModel} 设置的节点
     */
    dfsRightNode(root, node) {

        //判断左子结点是否为空
        if (root.right === null) {

            return root.right = node;

        }

        //递归遍历右子节点
        return this.dfsRightNode(root.right, node);

    }

}